package com.gzhryc.jdbc;

import com.gzhryc.jdbc.annotaion.Column;
import com.gzhryc.jdbc.annotaion.Id;
import com.gzhryc.jdbc.annotaion.NumberBranchTable;
import com.gzhryc.jdbc.log.Logger;
import com.gzhryc.jdbc.models.ConnectInfo;
import com.gzhryc.jdbc.utils.DbUtils;
import com.gzhryc.jdbc.utils.EntityUtils;
import com.gzhryc.jdbc.utils.HelperUtils;
import org.apache.commons.lang3.StringUtils;

import java.lang.reflect.Field;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicLong;

public class NumberBranchTableDao<T> extends BaseDao<T> {

    static Logger log = Logger.getLogger(DateBranchTableDao.class);

    protected String originalTableName;
    protected NumberBranchTable numberBranchTable;
    protected String suffix;

    public NumberBranchTableDao(String jdbcKey) {
        super(jdbcKey);
        this.numberBranchTable = clazz.getAnnotation(NumberBranchTable.class);
        this.originalTableName = this.tableName;
    }

    public NumberBranchTableDao(String jdbcKey, Long id) {
        super(jdbcKey);
        this.numberBranchTable = clazz.getAnnotation(NumberBranchTable.class);

        ConnectInfo info = ConnectionFactory.getConnectInfo(this.getJdbcKey());
        DbHelper helper = HelperUtils.createDbHelper(info.getKey());

        this.suffix = NumberBranchHelper.self().getTableSuffixByID(id);
        this.originalTableName = this.tableName;
        String tempTableName = originalTableName + "_" + suffix;
        try {
            if (helper.existTable(info.getDbName(), tempTableName)) {
                this.tableName = tempTableName;
            } else {
                DbUtils.createTable(info, clazz, tempTableName);
                this.tableName = tempTableName;
            }
        } catch (SQLException e) {
            log.error(e.getMessage(), e);
        }
    }

    public NumberBranchTableDao(String jdbcKey, String key) {
        super(jdbcKey);
        this.numberBranchTable = clazz.getAnnotation(NumberBranchTable.class);

        ConnectInfo info = ConnectionFactory.getConnectInfo(this.getJdbcKey());
        DbHelper helper = HelperUtils.createDbHelper(info.getKey());

        this.suffix = NumberBranchHelper.self().getTableSuffixByTail(key);
        this.originalTableName = this.tableName;
        String tempTableName = originalTableName + "_" + suffix;
        try {
            if (helper.existTable(info.getDbName(), tempTableName)) {
                this.tableName = tempTableName;
            } else {
                DbUtils.createTable(info, clazz, tempTableName);
                this.tableName = tempTableName;
            }
        } catch (SQLException e) {
            log.error(e.getMessage(), e);
        }
    }

    public Long getNewID(){
        if(suffix != null){
            AtomicLong idGenerator = NumberBranchHelper.self().getIdGenerator(this.originalTableName);
            if(idGenerator != null){
                String temp = suffix + idGenerator.incrementAndGet();
                return Long.valueOf(temp);
            }else{
                log.error("未能获取{{0}}表的ID生成器",this.originalTableName);
            }
        }
        return null;
    }

    public int insert(T obj) throws SQLException {
        Field idField = EntityUtils.getField(clazz,numberBranchTable.keyFieldName());
        if(idField != null) {
            Id idAnnotation = idField.getAnnotation(Id.class);
            if (idAnnotation != null) {
                try {
                    idField.setAccessible(true);
                    Object value = idField.get(obj);
                    if (value == null) {
                        idField.setLong(obj,getNewID());
                    }
                } catch (IllegalAccessException e) {
                    log.error(e.getMessage(),e);
                }
            }
        }
        return jdbcHelper.insert(this.tableName,obj);
    }

    public int insert(List<T> list) throws SQLException {
        Field idField = EntityUtils.getField(clazz,numberBranchTable.keyFieldName());
        if(idField != null) {
            Id idAnnotation = idField.getAnnotation(Id.class);
            if (idAnnotation != null) {
                for (T obj : list) {
                    try {
                        idField.setAccessible(true);
                        Object value = idField.get(obj);
                        if (value == null) {
                            idField.setLong(obj,getNewID());
                        }
                    } catch (IllegalAccessException e) {
                        log.error(e.getMessage(),e);
                    }
                }
            }
        }
        return jdbcHelper.insert(this.tableName,clazz,list);
    }

    public T getBranch(Conditions condition) throws SQLException {
        List<Field> fields = EntityUtils.findTableColumn(this.clazz);
        StringBuilder fieldStr = new StringBuilder();
        if (this.idField != null) {
            Column column = idField.getAnnotation(Column.class);
            String name = idField.getName();
            if (column != null && StringUtils.isNotBlank(column.name())) {
                name = column.name();
            }
            fieldStr.append(name);
        }
        for (int i = 0; i < fields.size(); i++) {
            Field field = fields.get(i);
            Column column = field.getAnnotation(Column.class);
            if (column != null) {
                if (idField != null && field.getName().equals(idField.getName())) {
                    continue;
                }
                String name = column.name();
                if (StringUtils.isBlank(name)) {
                    name = field.getName();
                }
                if (fieldStr.length() == 0) {
                    fieldStr.append(name);
                } else {
                    fieldStr.append(",").append(name);
                }
            }
        }

        Query query = new Query();
        String str = condition.toSql(query.getParams(), true);

        if(suffix != null && suffix.length() > 0){
            query.setSql("SELECT " + fieldStr.toString() + " FROM " + this.tableName + str);
            T obj = this.jdbcHelper.get(query, clazz);
            if (obj != null) {
                return obj;
            }
        }

        ConnectInfo info = ConnectionFactory.getConnectInfo(this.getJdbcKey());
        DbHelper helper = HelperUtils.createDbHelper(info.getKey());
        T obj = null;
        for (int i = 1; i <= 9; i++) {
            String tempTableName = originalTableName + i;
            if(!tempTableName.equals(this.tableName)) {
                if (helper.existTable(info.getDbName(), tempTableName)) {
                    query.setSql("SELECT " + fieldStr.toString() + " FROM " + tempTableName + str);
                    obj = this.jdbcHelper.get(query, clazz);
                    if (obj != null) {
                        break;
                    }
                }
            }
        }
        return obj;
    }

    public List<T> findBranchByCondition(Conditions condition) throws SQLException {
        List<Field> fields = EntityUtils.findTableColumn(this.clazz);
        StringBuilder fieldStr = new StringBuilder();
        if (this.idField != null) {
            Column column = idField.getAnnotation(Column.class);
            String name = idField.getName();
            if (column != null && StringUtils.isNotBlank(column.name())) {
                name = column.name();
            }
            fieldStr.append(name);
        }
        for (int i = 0; i < fields.size(); i++) {
            Field field = fields.get(i);
            Column column = field.getAnnotation(Column.class);
            if (column != null) {
                if (idField != null && field.getName().equals(idField.getName())) {
                    continue;
                }
                String name = column.name();
                if (StringUtils.isBlank(name)) {
                    name = field.getName();
                }
                if (fieldStr.length() == 0) {
                    fieldStr.append(name);
                } else {
                    fieldStr.append(",").append(name);
                }
            }
        }

        Query query = new Query();
        String str = condition.toSql(query.getParams(), true);

        ConnectInfo info = ConnectionFactory.getConnectInfo(this.getJdbcKey());
        DbHelper helper = HelperUtils.createDbHelper(info.getKey());
        List<T> result = null;
        for (int i = 1; i <= 9; i++) {
            String tempTableName = originalTableName + i;
            if(!tempTableName.equals(this.tableName)) {
                if (helper.existTable(info.getDbName(), tempTableName)) {
                    query.setSql("SELECT " + fieldStr.toString() + " FROM " + tempTableName + str);
                    List<T> obj = this.jdbcHelper.find(query, clazz);
                    if (obj != null) {
                        if(result == null){
                            result = new ArrayList<>();
                        }
                        result.addAll(obj);
                    }
                }
            }
        }
        return result;
    }
}